From 52a9a847def401730b86aeb2ef6dc1350eb6d998 Mon Sep 17 00:00:00 2001 From: Nicolas BESNARD Date: Thu, 23 Jan 2025 09:51:31 +0000 Subject: [PATCH] dhcpv6: fix solicit loop when server has no address available MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Problem: If Advertise with status 'noaddravail' is received while IA_NA is requested, a new Solicit is sent creating an infinite loop. Solution: Set IA_NA mode to none and send INFO-REQ message if no IA_NA or IA_PD are available. Signed-off-by: Nicolas BESNARD Signed-off-by: Paul Donald Link: https://github.com/openwrt/odhcp6c/pull/106 Signed-off-by: Álvaro Fernández Rojas --- src/dhcpv6.c | 11 ++++------- src/odhcp6c.c | 3 ++- src/odhcp6c.h | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index f2f3cd9..d97a732 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -551,6 +551,9 @@ int init_dhcpv6(const char *ifname) config_apply_dhcp_rtx(dhcpv6_retx); client_options = config_dhcp->client_options; + na_mode = config_dhcp->ia_na_mode; + pd_mode = config_dhcp->ia_pd_mode; + stateful_only_mode = config_dhcp->stateful_only_mode; sock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); if (sock < 0) @@ -679,14 +682,10 @@ enum { IOV_TOTAL }; -int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd, bool stateful_only) +int dhcpv6_get_ia_mode(void) { int mode = DHCPV6_UNKNOWN; - na_mode = na; - pd_mode = pd; - stateful_only_mode = stateful_only; - if (na_mode == IA_MODE_NONE && pd_mode == IA_MODE_NONE) mode = DHCPV6_STATELESS; else if (na_mode == IA_MODE_FORCE || pd_mode == IA_MODE_FORCE) @@ -1944,8 +1943,6 @@ int dhcpv6_promote_server_cand(void) dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = cand->sol_max_rt; dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_timeo = cand->inf_max_rt; - - dhcpv6_set_state(DHCPV6_SOLICIT); return -1; } diff --git a/src/odhcp6c.c b/src/odhcp6c.c index 78de3b7..3391aea 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -525,11 +525,12 @@ int main(_unused int argc, char* const argv[]) syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname); signal_usr1 = signal_usr2 = false; + dhcpv6_set_state(DHCPV6_SOLICIT); break; case DHCPV6_SOLICIT: - mode = dhcpv6_set_ia_mode(config_dhcp->ia_na_mode, config_dhcp->ia_pd_mode, config_dhcp->stateful_only_mode); + mode = dhcpv6_get_ia_mode(); if (mode == DHCPV6_STATELESS) { dhcpv6_set_state(DHCPV6_REQUEST); break; diff --git a/src/odhcp6c.h b/src/odhcp6c.h index ac2dd32..b117e8f 100644 --- a/src/odhcp6c.h +++ b/src/odhcp6c.h @@ -466,7 +466,7 @@ struct odhcp6c_opt { }; int init_dhcpv6(const char *ifname); -int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd, bool stateful_only); +int dhcpv6_get_ia_mode(void); int dhcpv6_promote_server_cand(void); int dhcpv6_send_request(enum dhcpv6_msg type); int dhcpv6_receive_response(enum dhcpv6_msg type); -- 2.30.2